/*
 * 
 *
 * Authors: Soeren Gebbert, soeren.gebbert@vti.bund.de
 *          Axel Don, axel.don@vti.bund.de
 *
 * Copyright:
 *
 * Johann Heinrich von Thünen-Institut
 * Institut für Agrarrelevante Klimaforschung
 *
 * Phone: +49 (0)531 596 2601
 *
 * Fax:+49 (0)531 596 2699
 *
 * Mail: ak@vti.bund.de
 *
 * Bundesallee 50
 * 38116 Braunschweig
 * Germany
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PUrunOSE.  See the
 * GNU General Public License for more details.
 */


#include <vector>
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <fstream>
#include <time.h>
#include "carb_particle.h"
#include "micr_cluster.h"
#include "initial_parameters.h"
#include "runtime_parameters.h"
#include "event_base.h"
#include "output.h"

using namespace std;

/* -------------------------------------------------------------------------- */
void write_carb_particle_output_files(int timestep, initial_parameters *init, vector<carb_particle*> &cp) {
    unsigned int i;
    ofstream carb_file;
    ofstream prof_file;
    char carb_name[1024];

    sprintf(carb_name, "%05i_%s", timestep, init->carb_filename.c_str());

    carb_file.exceptions(ifstream::failbit | ifstream::badbit);
    try {
        carb_file.open(carb_name);

        /* Write header*/
        carb_file << "X,Y,Z,age" << endl;

        /* Write files */
        for (i = 0; i < cp.size(); i++)
            carb_file << cp[i]->get_x() << "," << cp[i]->get_y() << "," << cp[i]->get_z() << "," << cp[i]->get_age() << endl;

    } catch (ifstream::failure e) {
        cerr << "Unable to write file " << carb_name << " Error: " << e.what() << endl;
    }

    carb_file.close();
}

/* -------------------------------------------------------------------------- */
void write_micr_cluster_output_files(int timestep, initial_parameters *init, vector<micr_cluster*> &mc) {
    unsigned int i;
    ofstream micr_file;
    char micr_name[1024];

    sprintf(micr_name, "%05i_%s", timestep, init->micr_filename.c_str());

    micr_file.exceptions(ifstream::failbit | ifstream::badbit);
    try {
        micr_file.open(micr_name);

        /* Write header*/
        micr_file << "X,Y,Z,mass,radius,contacts" << endl;

        /* Write files */
        for (i = 0; i < mc.size(); i++)
            micr_file << mc[i]->get_x() << "," << mc[i]->get_y() << "," << mc[i]->get_z() << "," << mc[i]->get_mass() << "," << mc[i]->get_radius()
            << "," << mc[i]->get_contacts() << endl;

    } catch (ifstream::failure e) {
        cerr << "Unable to write file " << micr_name << " Error: " << e.what() << endl;
    }

    micr_file.close();
}

/* -------------------------------------------------------------------------- */
void write_profile_output_file(int timestep, initial_parameters *init, 
                               vector<micr_cluster*> &mc, 
                               vector<carb_particle*> &cp) {
    unsigned int i;
    ofstream prof_file;
    char prof_name[1024];
    
    /* We write the profile data */
    
    sprintf(prof_name, "%05i_%s", timestep, init->profile_filename.c_str());
    
    prof_file.exceptions(ifstream::failbit | ifstream::badbit);
    try {
        double z;
        double min = 0;
        double max = -1 * fabs(init->depth_steps);
        vector<bool> c_check;
        vector<bool> m_check;
        
        /* Open the profile file */
        prof_file.open(prof_name);
        
        /* Write header*/
        prof_file << "depth,number_of_c_particles,average_c_age,c_mass,number_of_m_cluster,m_mass,number_of_m_contacts,m_mean_radius" << endl;
        
        for (i = 0; i < cp.size(); i++)
            c_check.push_back(false);
        for (i = 0; i < mc.size(); i++)
            m_check.push_back(false);
        
        while(min > init->depth) {
            /* Carbon paritcles */
            int num_particles = 0;
            int sum_age = 0;
            double sum_c_mass = 0.0;
            double average_age = 0;
            
            /* Microorganism cluster */
            int num_micro = 0;
            double sum_m_mass = 0.0;
            int sum_contacts = 0;
            double sum_radius = 0.0;
            double mean_radius = 0.0;
            
            for (i = 0; i < cp.size(); i++) {
                if(c_check[i] == false) {
                    z = cp[i]->get_z();
                    if(z <= min && z > max) {
                        num_particles++;
                        sum_age += cp[i]->get_age();
                        sum_c_mass += cp[i]->get_mass();
                        c_check[i] = true;
                    }
                }
            }         
            
            if(num_particles > 0)
                average_age = double(sum_age)/double(num_particles);
            
            for (i = 0; i < mc.size(); i++) {
                if(m_check[i] == false) {
                    z = mc[i]->get_z();
                    if(z <= min && z > max) {
                        num_micro++;
                        sum_contacts += mc[i]->get_contacts();
                        sum_m_mass += mc[i]->get_mass();
                        sum_radius += mc[i]->get_radius();
                        m_check[i] = true;
                    }
                }
            }
            
            if(num_micro > 0)
                mean_radius = double(sum_radius)/double(num_micro);
            
            // depth,number_of_c_particles,average_c_age,c_mass
            // number_of_m_cluster,m_mass,number_of_m_contacts,m_mean_radius
        
            /* Write the data */
            prof_file << max << "," << num_particles << "," << average_age << "," << sum_c_mass;
            prof_file << "," << num_micro << "," << sum_m_mass << "," << sum_contacts << "," << mean_radius << endl;
            
            /* Next interval */
            min = max;
            max += -1 * fabs(init->depth_steps);
        }
    } catch (ifstream::failure e) {
        cerr << "Unable to write file " << prof_name << " Error: " << e.what() << endl;
    }

    prof_file.close();
}